package com.sunxueqi.project.monitor.service.impl;

import java.lang.management.ManagementFactory;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Service;

import com.sunxueqi.common.utils.IpUtils;
import com.sunxueqi.project.monitor.service.IServerService;

import cn.hutool.core.date.BetweenFormater.Level;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.unit.DataSizeUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.GlobalMemory;
import oshi.hardware.HardwareAbstractionLayer;
import oshi.software.os.FileSystem;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;
import oshi.util.Util;

@Service
public class ServerServiceImpl implements IServerService{

	Log log = LogFactory.get();
	
	@Override
	public Map<String, Object> getServerInfo() {
		
		Map<String, Object> map = new HashMap<String, Object>();
		
		try {
			
			SystemInfo si = new SystemInfo();
			OperatingSystem os = si.getOperatingSystem();
			HardwareAbstractionLayer hal = si.getHardware();
			
			map.put("system", getSystemInfo(os));
			map.put("disk", getDiskInfo(os));
			map.put("memory", getMemoryInfo(hal.getMemory()));
			map.put("cpu", getCpuInfo(hal.getProcessor()));
			map.put("time", DateTime.now().toString());
		
		} catch (Exception e) {}
		
		return map;
	}
	
	/**
	 * 获取系统信息，服务运行时间，服务器ip
	 * @param os
	 * @return
	 */
	private Map<String, Object> getSystemInfo(OperatingSystem os) {
		Map<String, Object> systemInfo = new HashMap<String, Object>();
		
		// 计算项目运行时长
		String runTime = DateUtil.formatBetween(System.currentTimeMillis() - ManagementFactory.getRuntimeMXBean().getStartTime(), Level.HOUR);
		systemInfo.put("time", runTime);
		systemInfo.put("os", os.toString());
		systemInfo.put("ip", IpUtils.getHostIp());
		return systemInfo;
	}
	
	/**
	 * 获取磁盘信息
	 * @param os
	 * @return
	 */
	private Map<String, Object> getDiskInfo(OperatingSystem os) {
		Map<String, Object> diskInfo = new HashMap<String, Object>();
		
		FileSystem fileSystem = os.getFileSystem();
		List<OSFileStore> fileStoreArray = fileSystem.getFileStores();
		for (OSFileStore fileStore : fileStoreArray) {
			
			// 磁盘总空间
			long total = fileStore.getTotalSpace();
			// 磁盘已用空间
			long used = fileStore.getTotalSpace() - fileStore.getUsableSpace();
			// 磁盘可用空间
			long usable = fileStore.getUsableSpace();
			
			diskInfo.put("total", total > 0 ? DataSizeUtil.format(total) : "?");
			diskInfo.put("used", DataSizeUtil.format(used));
			diskInfo.put("usable", DataSizeUtil.format(usable));
			
			// 磁盘已用空间占比
			diskInfo.put("usage", NumberUtil.roundStr(NumberUtil.div(used, total)*100, 2));
		}
		
		return diskInfo;
	}
	
	/**
	 * 获取CPU相关信息
	 * @param centralProcessor
	 * @return
	 */
	private Map<String, Object> getCpuInfo(CentralProcessor processor) {
		Map<String, Object> cpuInfo = new HashMap<String, Object>();
		cpuInfo.put("name", processor.getProcessorIdentifier().getName());
		cpuInfo.put("package", processor.getPhysicalPackageCount() + "个物理CPU");
		cpuInfo.put("core", processor.getPhysicalProcessorCount() + "个物理核心");
		cpuInfo.put("coreNumber", processor.getPhysicalProcessorCount());
		cpuInfo.put("logic", processor.getLogicalProcessorCount() + "个逻辑CPU");
		
		long[] prevTicks = processor.getSystemCpuLoadTicks();
		Util.sleep(1000);
		long[] ticks = processor.getSystemCpuLoadTicks();
        long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
        long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
        long sys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
        long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
        long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
        long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
        long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
        long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
        long totalCpu = user + nice + sys + idle + iowait + irq + softirq + steal;
		
        // 已占用的cpu百分比
        cpuInfo.put("usage", NumberUtil.roundStr(NumberUtil.div(user + sys, totalCpu)*100, 2));
        // 空闲的cpu百分比
		cpuInfo.put("idle", NumberUtil.roundStr(NumberUtil.div(idle, totalCpu)*100, 2));
		
		return cpuInfo;
	}
	
	/**
	 * 获取内存信息
	 * @param memory
	 * @return
	 */
	private Map<String, Object> getMemoryInfo(GlobalMemory memory) {
		
		long total = memory.getTotal();
		long usable = memory.getAvailable();
		long used = total - usable;
		
		Map<String, Object> memoryInfo = new HashMap<String, Object>();
		memoryInfo.put("total", DataSizeUtil.format(total));
		memoryInfo.put("usable", DataSizeUtil.format(usable));
		memoryInfo.put("used", DataSizeUtil.format(used));
		memoryInfo.put("usage", NumberUtil.roundStr(NumberUtil.div(used, total)*100, 2));
		
		return memoryInfo;
				
	}
	
}
